// ComfyUI-xhh OutpaintPanelV2 v1.2 - 外补面板V2拖拽组件
import { app } from "../../scripts/app.js";

class OutpaintPanelV2
{
    constructor(node)
    {
        this.node = node;
        
        // 初始化节点属性
        this.node.properties = { 
            imageWidth: 512,     // 原图宽度
            imageHeight: 512,    // 原图高度
            targetWidth: 1024,   // 目标宽度
            targetHeight: 1024,  // 目标高度
            up: 0,               // 顶部偏移
            left: 0,             // 左侧偏移
            previewScale: 1.0,   // 预览缩放比例
            showGrid: true,      // 显示网格
            showInfo: true,      // 显示信息
            autoAdjustCanvas: true, // 自动调整画布大小
            canvasAdjusted: false,  // 画布是否已调整
            originalImageHash: null // 原图哈希值
        };
        
        // 内部相对位置 (0-1范围)
        this.node.relativePos = { x: 0, y: 0 };
        
        // 设置初始节点尺寸 - 使用计算的合适尺寸
        const initialSize = this.node.computeSize();
        this.node.size = initialSize;
        
        console.log("[OutpaintPanelV2] 初始化节点尺寸:", initialSize);
        
        // 重写节点的背景绘制函数，确保参数区域有颜色
        this.node.onDrawBackground = function(ctx) {
            // 调用原始的背景绘制
            if (this.onDrawBackground_original) {
                this.onDrawBackground_original(ctx);
            }
            
            // 绘制参数区域背景
            if (!this.flags.collapsed) {
                this.drawParameterArea(ctx);
            }
        };
        
        // 确保widgets正常显示，不隐藏任何控件
        this.node.onAdded = function ()
        {
            // 不隐藏widgets，让用户能看到和操作所有参数
            console.log("[OutpaintPanelV2] 节点已添加，widgets数量:", this.widgets?.length);
            
            // 重新计算节点尺寸
            const newSize = this.computeSize();
            this.size = newSize;
            console.log("[OutpaintPanelV2] 节点添加后重新计算尺寸:", newSize);
            
            this.updateImageSize();
            this.updateLayoutParameters();
            
            // 暂时移除手动触发按钮的自动添加，避免布局问题
            // setTimeout(() => {
            //     this.addManualTrigger();
            // }, 1000);
        };
        
        // 添加手动触发按钮
        this.node.addManualTrigger = function() {
            try {
                // 检查是否已经存在手动触发按钮
                const existingButton = this.widgets?.find(w => w.name === "manual_trigger");
                if (existingButton) {
                    console.log("[OutpaintPanelV2] 手动触发按钮已存在");
                    return;
                }
                
                // 使用ComfyUI的标准方式创建按钮
                const LiteGraph = window.LiteGraph;
                if (LiteGraph && LiteGraph.LGraphNode) {
                    // 创建按钮widget
                    const buttonWidget = {
                        name: "manual_trigger",
                        type: "button",
                        value: "手动触发调整",
                        callback: (value, widget, node) => {
                            console.log("[OutpaintPanelV2] 手动触发调整被点击");
                            try {
                                node.updateImageSize();
                                node.autoAdjustCanvasSize();
                                node.setDirtyCanvas(true);
                                console.log("[OutpaintPanelV2] 手动触发调整完成");
                            } catch (e) {
                                console.log("[OutpaintPanelV2] 手动触发调整失败:", e);
                            }
                        }
                    };
                    
                    // 添加到widgets列表
                    if (this.widgets) {
                        this.widgets.push(buttonWidget);
                        console.log("[OutpaintPanelV2] 成功添加手动触发按钮");
                    } else {
                        console.log("[OutpaintPanelV2] widgets列表不存在");
                    }
                } else {
                    console.log("[OutpaintPanelV2] LiteGraph不可用");
                }
            } catch (e) {
                console.log("[OutpaintPanelV2] 添加手动触发按钮失败:", e);
            }
        };
        
        // 配置加载时的处理
        this.node.onConfigure = function ()
        {
            this.updateImageSize();
            this.updateLayoutParameters();
        }
        
        // 图配置完成后的处理
        this.node.onGraphConfigured = function ()
        {
            this.configured = true;
            
            // 重新计算节点尺寸
            const newSize = this.computeSize();
            this.size = newSize;
            console.log("[OutpaintPanelV2] 图配置完成后重新计算尺寸:", newSize);
            
            this.updateProperties();
            this.updateLayoutParameters();
        }
        
        // 监听widget值变化
        this.node.onWidgetChanged = function(widget) {
            console.log("[OutpaintPanelV2] Widget变化:", widget.name, "=", widget.value);
            
            // 立即更新属性
            this.updateProperties();
            
            // 如果是尺寸相关参数，强制重绘
            if (widget.name === "width" || widget.name === "height") {
                console.log("[OutpaintPanelV2] 尺寸参数变化，强制重绘");
                this.setDirtyCanvas(true);
                if (this.graph) {
                    this.graph.setisChangedFlag(this.id);
                }
            }
        }
        
        // 监听输入连接变化
        this.node.onConnectionsChange = function(type, slot, connected, link_info, output) {
            console.log("[OutpaintPanelV2] 连接变化:", type, slot, connected);
            
            if (type === LiteGraph.INPUT && slot === 0 && connected) {
                // 输入图片连接时，延迟检查图片尺寸
                setTimeout(() => {
                    console.log("[OutpaintPanelV2] 连接后检查图片尺寸");
                    this.updateImageSize();
                    this.setDirtyCanvas(true);
                }, 100);
                
                // 再次延迟检查，确保图片加载完成
                setTimeout(() => {
                    console.log("[OutpaintPanelV2] 延迟检查图片尺寸");
                    this.updateImageSize();
                    this.setDirtyCanvas(true);
                }, 500);
            }
        }
        
        // 绘制回退的图片区域（当无法获取实际图片时）- 移除调试颜色
        this.node.drawFallbackImageArea = function(ctx, imgX, imgY, imgScaledW, imgScaledH) {
            // 移除半透明红色背景
            // ctx.fillStyle = "rgba(255,100,100,0.3)";
            // ctx.fillRect(imgX, imgY, imgScaledW, imgScaledH);
            
            // 移除边框
            // ctx.strokeStyle = "rgba(255,100,100,0.8)";
            // ctx.lineWidth = 3;
            // ctx.strokeRect(imgX, imgY, imgScaledW, imgScaledH);
            
            // 移除占位文字
            // ctx.fillStyle = "rgba(255,255,255,0.8)";
            // ctx.font = "12px Arial";
            // ctx.textAlign = "center";
            // const textX = imgX + imgScaledW / 2;
            // const textY = imgY + imgScaledH / 2;
            // ctx.fillText("原图区域", textX, textY);
            // ctx.textAlign = "left"; // 恢复默认对齐
        }
        
        // 绘制调试信息
        this.node.drawDebugInfo = function(ctx, previewArea, offsetX, offsetY, scaledW, scaledH, imgX, imgY, imgScaledW, imgScaledH) {
            // 在节点底部绘制调试信息
            const debugY = this.size[1] - 80;
            const debugX = 10;
            
            // 绘制调试信息背景
            ctx.fillStyle = "rgba(0,0,0,0.7)";
            ctx.fillRect(debugX - 5, debugY - 5, 300, 75);
            
            // 绘制调试信息
            ctx.fillStyle = "rgba(255,255,255,0.9)";
            ctx.font = "10px Arial";
            ctx.textAlign = "left";
            
            const lines = [
                `原图: ${this.properties.imageWidth}x${this.properties.imageHeight}`,
                `目标: ${this.properties.targetWidth}x${this.properties.targetHeight}`,
                `位置: (${this.properties.left}, ${this.properties.up})`,
                `预览区域: ${Math.round(previewArea.x)},${Math.round(previewArea.y)} ${Math.round(previewArea.width)}x${Math.round(previewArea.height)}`,
                `画布区域: ${Math.round(offsetX)},${Math.round(offsetY)} ${Math.round(scaledW)}x${Math.round(scaledH)}`,
                `原图区域: ${Math.round(imgX)},${Math.round(imgY)} ${Math.round(imgScaledW)}x${Math.round(imgScaledH)}`
            ];
            
            lines.forEach((line, index) => {
                ctx.fillText(line, debugX, debugY + index * 12);
            });
            
            // 绘制颜色图例
            const legendY = debugY + 60;
            const legendItems = [
                { color: "rgba(100,200,100,0.8)", text: "参数区域" },
                { color: "rgba(100,100,100,0.8)", text: "间隔区域" },
                { color: "rgba(60,60,80,0.95)", text: "图片预览区域" },
                { color: "rgba(255,150,50,0.8)", text: "画布区域" },
                { color: "rgba(255,100,100,0.8)", text: "原图区域" }
            ];
            
            legendItems.forEach((item, index) => {
                const x = debugX + index * 60; // 减小间距以适应更多图例
                ctx.fillStyle = item.color;
                ctx.fillRect(x, legendY, 10, 10);
                ctx.fillStyle = "rgba(255,255,255,0.9)";
                ctx.fillText(item.text, x + 15, legendY + 8);
            });
        }
        
        // 更新布局参数
        this.node.updateLayoutParameters = function()
        {
            // 动态计算布局参数
            const nodeWidth = this.size[0];
            const nodeHeight = this.size[1];
            
            // 计算核心参数widgets高度（不包括手动触发按钮）
            let coreWidgetsHeight = 0;
            let totalWidgetsHeight = 0;
            if (this.widgets) {
                for (let widget of this.widgets) {
                    if (!widget.hidden) {
                        const widgetHeight = LiteGraph.NODE_WIDGET_HEIGHT + 4;
                        totalWidgetsHeight += widgetHeight;
                        
                        // 只计算核心参数widgets
                        if (['width', 'height', 'up', 'left', 'fill_mode', 'feather'].includes(widget.name)) {
                            coreWidgetsHeight += widgetHeight;
                        }
                    }
                }
            }
            
            // 添加节点头部高度和额外间距
            const nodeHeaderHeight = 30; // 节点标题栏高度
            const extraPadding = 25; // 增加额外的安全间距，防止重叠
            
            // 参数区域高度（基于核心widgets）
            const paramAreaHeight = Math.max(120, coreWidgetsHeight + 10);
            
            // 间隔区域高度（与参数区域相同）
            const gapAreaHeight = paramAreaHeight;
            
            // 预览区域位置和大小 - 直接紧贴间隔区域，去掉额外间距
            this.previewTop = nodeHeaderHeight + paramAreaHeight + gapAreaHeight;
            this.previewLeft = 10;
            this.previewWidth = Math.max(200, nodeWidth - 20);
            
            // 预览区域高度：节点总高度减去顶部偏移和底部信息区域
            const bottomInfoHeight = 60; // 为底部信息文本留出空间
            const bottomPadding = 10; // 底部边距
            this.previewHeight = Math.max(180, nodeHeight - this.previewTop - bottomInfoHeight - bottomPadding);
            
            console.log("[OutpaintPanelV2] 布局更新:", {
                nodeSize: this.size,
                coreWidgetsHeight: coreWidgetsHeight,
                totalWidgetsHeight: totalWidgetsHeight,
                paramAreaHeight: paramAreaHeight,
                gapAreaHeight: gapAreaHeight,
                nodeHeaderHeight: nodeHeaderHeight,
                areas: {
                    paramArea: {
                        top: nodeHeaderHeight,
                        height: paramAreaHeight
                    },
                    gapArea: {
                        top: nodeHeaderHeight + paramAreaHeight,
                        height: gapAreaHeight
                    },
                    previewArea: {
                        top: this.previewTop,
                        left: this.previewLeft,
                        width: this.previewWidth,
                        height: this.previewHeight
                    }
                }
            });
        }
        
        // 更新图片尺寸信息
        this.node.updateImageSize = function()
        {
            try {
                // 获取输入的图片信息
                if (this.inputs && this.inputs[0] && this.inputs[0].link) {
                    const link = app.graph.links[this.inputs[0].link];
                    if (link && link.origin_slot !== undefined) {
                        const sourceNode = app.graph.getNodeById(link.origin_id);
                        if (sourceNode && sourceNode.imgs && sourceNode.imgs.length > 0) {
                            const img = sourceNode.imgs[0];
                            const newWidth = img.naturalWidth || img.width || 512;
                            const newHeight = img.naturalHeight || img.height || 512;
                            
                            console.log("[OutpaintPanelV2] 检测到图片:", newWidth + "x" + newHeight);
                            
                            // 计算图片哈希值（简单的哈希）
                            const newHash = `${newWidth}x${newHeight}`;
                            
                            // 检查是否是新图片或尺寸变化
                            if (this.properties.originalImageHash !== newHash || 
                                this.properties.imageWidth !== newWidth || 
                                this.properties.imageHeight !== newHeight) {
                                
                                console.log("[OutpaintPanelV2] 检测到新图片或尺寸变化:", newWidth + "x" + newHeight);
                                
                                this.properties.imageWidth = newWidth;
                                this.properties.imageHeight = newHeight;
                                this.properties.originalImageHash = newHash;
                                
                                // 重置画布调整状态，允许重新调整
                                this.properties.canvasAdjusted = false;
                                
                                // 自动调整画布大小
                                if (this.properties.autoAdjustCanvas) {
                                    console.log("[OutpaintPanelV2] 触发自动调整画布大小");
                                    this.autoAdjustCanvasSize();
                                } else {
                                    console.log("[OutpaintPanelV2] 自动调整已禁用");
                                }
                            }
                        } else {
                            console.log("[OutpaintPanelV2] 源节点没有图片");
                        }
                    } else {
                        console.log("[OutpaintPanelV2] 没有输入连接");
                    }
                } else {
                    console.log("[OutpaintPanelV2] 输入端口不存在");
                }
            } catch (e) {
                console.log("[OutpaintPanelV2] 无法获取图片尺寸:", e);
            }
        }
        
        // 自动调整画布大小
        this.node.autoAdjustCanvasSize = function()
        {
            try {
                const maxDimension = Math.max(this.properties.imageWidth, this.properties.imageHeight);
                // 确保画布大小是8的倍数
                const newCanvasSize = Math.ceil(maxDimension / 8) * 8;
                
                console.log("[OutpaintPanelV2] 自动调整画布大小:", newCanvasSize + "x" + newCanvasSize);
                
                // 更新widgets中的width和height值
                if (this.widgets) {
                    const widthWidget = this.widgets.find(w => w.name === "width");
                    const heightWidget = this.widgets.find(w => w.name === "height");
                    
                    if (widthWidget) {
                        widthWidget.value = newCanvasSize;
                        widthWidget.callback(newCanvasSize);
                        console.log("[OutpaintPanelV2] 更新width widget:", newCanvasSize);
                    }
                    if (heightWidget) {
                        heightWidget.value = newCanvasSize;
                        heightWidget.callback(newCanvasSize);
                        console.log("[OutpaintPanelV2] 更新height widget:", newCanvasSize);
                    }
                }
                
                // 计算居中位置
                const centerUp = Math.max(0, Math.floor((newCanvasSize - this.properties.imageHeight) / 2));
                const centerLeft = Math.max(0, Math.floor((newCanvasSize - this.properties.imageWidth) / 2));
                
                console.log("[OutpaintPanelV2] 居中计算:", {
                    canvasSize: newCanvasSize,
                    imageWidth: this.properties.imageWidth,
                    imageHeight: this.properties.imageHeight,
                    centerLeft: centerLeft,
                    centerUp: centerUp
                });
                
                // 更新up和left值
                const upWidget = this.widgets.find(w => w.name === "up");
                const leftWidget = this.widgets.find(w => w.name === "left");
                
                if (upWidget) {
                    upWidget.value = centerUp;
                    upWidget.callback(centerUp);
                    console.log("[OutpaintPanelV2] 更新up widget:", centerUp);
                }
                if (leftWidget) {
                    leftWidget.value = centerLeft;
                    leftWidget.callback(centerLeft);
                    console.log("[OutpaintPanelV2] 更新left widget:", centerLeft);
                }
                
                // 更新属性
                this.properties.targetWidth = newCanvasSize;
                this.properties.targetHeight = newCanvasSize;
                this.properties.up = centerUp;
                this.properties.left = centerLeft;
                this.properties.canvasAdjusted = true;
                
                console.log("[OutpaintPanelV2] 画布调整完成，居中位置:", centerLeft + "," + centerUp);
                
                // 强制更新属性
                this.updateProperties();
                
                // 触发重绘
                this.setDirtyCanvas(true);
                if (this.graph) {
                    this.graph.setisChangedFlag(this.id);
                }
                
            } catch (e) {
                console.log("[OutpaintPanelV2] 自动调整画布失败:", e);
            }
        }
        
        // 属性变化处理
        this.node.updateProperties = function()
        {
            if (!this.configured || this.updating) return;
            
            // 从widgets获取最新值，确保参数正确传递
            try {
                if (this.widgets && this.widgets.length >= 5) {
                    // 通过名称查找widgets，更准确
                    let widthWidget = this.widgets.find(w => w.name === "width");
                    let heightWidget = this.widgets.find(w => w.name === "height");
                    let upWidget = this.widgets.find(w => w.name === "up");
                    let leftWidget = this.widgets.find(w => w.name === "left");
                    let fillModeWidget = this.widgets.find(w => w.name === "fill_mode");
                    
                    const newWidth = widthWidget ? Math.max(64, parseInt(widthWidget.value) || 1024) : 1024;
                    const newHeight = heightWidget ? Math.max(64, parseInt(heightWidget.value) || 1024) : 1024;
                    const newUp = upWidget ? Math.max(0, parseInt(upWidget.value) || 0) : 0;
                    const newLeft = leftWidget ? Math.max(0, parseInt(leftWidget.value) || 0) : 0;
                    
                    // 只在值真正改变时更新
                    if (this.properties.targetWidth !== newWidth || 
                        this.properties.targetHeight !== newHeight ||
                        this.properties.up !== newUp ||
                        this.properties.left !== newLeft) {
                        
                        this.properties.targetWidth = newWidth;
                        this.properties.targetHeight = newHeight;
                        this.properties.up = newUp;
                        this.properties.left = newLeft;
                        
                        console.log("[OutpaintPanelV2] 参数更新:", {
                            width: this.properties.targetWidth,
                            height: this.properties.targetHeight,
                            up: this.properties.up,
                            left: this.properties.left,
                            fill_mode: fillModeWidget ? fillModeWidget.value : "edge_extend"
                        });
                        
                        // 触发重绘
                        this.setDirtyCanvas(true);
                    }
                }
            } catch (e) {
                console.log("[OutpaintPanelV2] 参数更新失败:", e);
            }
            
            // 边界检查
            const maxUp = Math.max(0, this.properties.targetHeight - this.properties.imageHeight);
            const maxLeft = Math.max(0, this.properties.targetWidth - this.properties.imageWidth);
            
            if (this.properties.up > maxUp) this.properties.up = maxUp;
            if (this.properties.left > maxLeft) this.properties.left = maxLeft;
            
            // 更新相对位置
            if (maxUp > 0) {
                this.relativePos.y = this.properties.up / maxUp;
            } else {
                this.relativePos.y = 0;
            }
            
            if (maxLeft > 0) {
                this.relativePos.x = this.properties.left / maxLeft;
            } else {
                this.relativePos.x = 0;
            }
        }
        
        // 绘制参数区域背景（已移除调试颜色）
        this.node.drawParameterArea = function(ctx)
        {
            // 计算参数区域 - 只计算核心参数widgets，不包括手动触发按钮
            const nodeHeaderHeight = 30;
            let widgetsHeight = 0;
            let coreWidgetsCount = 0;
            
            if (this.widgets) {
                for (let widget of this.widgets) {
                    if (!widget.hidden) {
                        // 只计算核心参数widgets（width, height, up, left, fill_mode, feather）
                        if (['width', 'height', 'up', 'left', 'fill_mode', 'feather'].includes(widget.name)) {
                            widgetsHeight += LiteGraph.NODE_WIDGET_HEIGHT + 4;
                            coreWidgetsCount++;
                        }
                    }
                }
            }
            
            // 确保参数区域有合理的最小高度
            const minHeight = 120; // 最小高度
            const calculatedHeight = Math.max(minHeight, widgetsHeight + 10);
            
            const paramArea = {
                x: 0,
                y: nodeHeaderHeight,
                width: this.size[0],
                height: calculatedHeight
            };
            
            // 绘制间隔区域 - 高度与参数区域相同
            const gapArea = {
                x: 0,
                y: paramArea.y + paramArea.height,
                width: this.size[0],
                height: calculatedHeight
            };
            
            // 保存当前canvas状态
            ctx.save();
            
            // 移除所有调试背景颜色和边框，只保留基本功能
            // 参数区域和间隔区域不再显示背景色
            
            // 恢复canvas状态
            ctx.restore();
            
            console.log("[OutpaintPanelV2] 绘制参数区域和间隔区域（无调试颜色）:", {
                paramArea: paramArea,
                gapArea: gapArea,
                coreWidgetsCount: coreWidgetsCount,
                totalWidgets: this.widgets?.length || 0
            });
        }
        
        // 绘制前景（拖拽界面）
        this.node.onDrawForeground = function(ctx)
        {
            if (this.flags.collapsed) return false;
            
            this.configured = true;
            this.updateImageSize();
            this.updateProperties();
            this.updateLayoutParameters();
            
            // 绘制参数区域背景 - 确保在最前面绘制，使用更高的z-index
            this.drawParameterArea(ctx);
            
            console.log("[OutpaintPanelV2] 绘制前景，节点尺寸:", this.size);
            
            // 强制重绘参数区域，确保不被覆盖
            setTimeout(() => {
                if (!this.flags.collapsed) {
                    this.drawParameterArea(ctx);
                }
            }, 10);
            
            const imgW = this.properties.imageWidth;
            const imgH = this.properties.imageHeight;
            const targetW = this.properties.targetWidth;
            const targetH = this.properties.targetHeight;
            
            // 计算预览区域（使用动态布局）
            const previewArea = {
                x: this.previewLeft,
                y: this.previewTop,
                width: this.previewWidth,
                height: this.previewHeight
            };
            
            // 计算缩放比例
            const scaleX = previewArea.width / targetW;
            const scaleY = previewArea.height / targetH;
            const scale = Math.min(scaleX, scaleY, 1.0);
            
            // 居中显示
            const scaledW = targetW * scale;
            const scaledH = targetH * scale;
            const offsetX = previewArea.x + (previewArea.width - scaledW) / 2;
            const offsetY = previewArea.y + (previewArea.height - scaledH) / 2;
            
            // 移除预览区域背景颜色和标识文字
            // ctx.fillStyle = "rgba(40,40,150,0.95)"; // 移除蓝色背景
            // ctx.fillRect(previewArea.x, previewArea.y, previewArea.width, previewArea.height);
            
            // 移除预览区域边框
            // ctx.strokeStyle = "rgba(80,120,255,1.0)"; // 移除蓝色边框
            // ctx.lineWidth = 3;
            // ctx.strokeRect(previewArea.x, previewArea.y, previewArea.width, previewArea.height);
            
            // 移除区域标识文字
            // ctx.fillStyle = "rgba(255,255,255,1.0)";
            // ctx.font = "12px Arial";
            // ctx.textAlign = "left";
            // ctx.fillText("图片预览区域", previewArea.x + 5, previewArea.y + 15);
            
            // 绘制画布区域边框 - 恢复边框显示
            ctx.strokeStyle = "rgba(255,150,50,0.8)"; // 橙色边框
            ctx.lineWidth = 2;
            ctx.strokeRect(offsetX, offsetY, scaledW, scaledH);
            
            // 移除画布区域标识文字
            // ctx.fillStyle = "rgba(255,150,50,0.8)";
            // ctx.font = "10px Arial";
            // ctx.textAlign = "left";
            // ctx.fillText("画布区域", offsetX + 5, offsetY + 15);
            
            // 绘制网格
            if (this.properties.showGrid) {
                ctx.strokeStyle = "rgba(80,80,80,0.4)";
                ctx.lineWidth = 0.5;
                const gridSize = 50 * scale;
                
                // 垂直线
                for (let x = offsetX; x <= offsetX + scaledW; x += gridSize) {
                    ctx.beginPath();
                    ctx.moveTo(x, offsetY);
                    ctx.lineTo(x, offsetY + scaledH);
                    ctx.stroke();
                }
                
                // 水平线
                for (let y = offsetY; y <= offsetY + scaledH; y += gridSize) {
                    ctx.beginPath();
                    ctx.moveTo(offsetX, y);
                    ctx.lineTo(offsetX + scaledW, y);
                    ctx.stroke();
                }
            }
            
            // 计算原图在预览中的位置
            const imgScaledW = imgW * scale;
            const imgScaledH = imgH * scale;
            const imgX = offsetX + this.properties.left * scale;
            const imgY = offsetY + this.properties.up * scale;
            
            // 获取并绘制实际的输入图片
            let actualImage = null;
            try {
                // 方法1：尝试从输入节点获取图片
                if (this.inputs && this.inputs[0] && this.inputs[0].link) {
                    const link = app.graph.links[this.inputs[0].link];
                    if (link && link.origin_slot !== undefined) {
                        const sourceNode = app.graph.getNodeById(link.origin_id);
                        if (sourceNode && sourceNode.imgs && sourceNode.imgs.length > 0) {
                            actualImage = sourceNode.imgs[0];
                            console.log("[OutpaintPanelV2] 从源节点获取图片成功");
                        }
                    }
                }
                
                // 方法2：如果方法1失败，尝试从节点自身获取图片
                if (!actualImage && this.imgs && this.imgs.length > 0) {
                    actualImage = this.imgs[0];
                    console.log("[OutpaintPanelV2] 从自身节点获取图片成功");
                }
                
                // 方法3：尝试获取app中最近处理的图片
                if (!actualImage && app.nodeOutputs) {
                    // 遍历最近的节点输出寻找图片
                    for (let nodeId in app.nodeOutputs) {
                        const outputs = app.nodeOutputs[nodeId];
                        if (outputs && outputs.images && outputs.images.length > 0) {
                            const imgUrl = `/view?filename=${outputs.images[0].filename}&subfolder=${outputs.images[0].subfolder}&type=${outputs.images[0].type}`;
                            const img = new Image();
                            img.src = imgUrl;
                            if (img.complete) {
                                actualImage = img;
                                console.log("[OutpaintPanelV2] 从app输出获取图片成功");
                                break;
                            }
                        }
                    }
                }
            } catch (e) {
                console.log("[OutpaintPanelV2] 获取输入图片失败:", e);
            }
            
            // 绘制原图区域
            if (actualImage) {
                // 绘制实际的图片
                try {
                    // 保存当前canvas状态
                    ctx.save();
                    
                    // 设置裁剪区域，确保图片不超出原图区域
                    ctx.beginPath();
                    ctx.rect(imgX, imgY, imgScaledW, imgScaledH);
                    ctx.clip();
                    
                    // 绘制图片，保持宽高比
                    ctx.drawImage(actualImage, imgX, imgY, imgScaledW, imgScaledH);
                    
                    // 恢复canvas状态
                    ctx.restore();
                    
                    // 移除图片边框和标识
                    // ctx.strokeStyle = "rgba(255,100,100,0.8)"; // 移除红色边框
                    // ctx.lineWidth = 3;
                    // ctx.strokeRect(imgX, imgY, imgScaledW, imgScaledH);
                    
                    // 移除原图区域标识
                    // ctx.fillStyle = "rgba(255,100,100,0.8)";
                    // ctx.font = "10px Arial";
                    // ctx.textAlign = "left";
                    // ctx.fillText("原图区域", imgX + 5, imgY + 15);
                    
                } catch (e) {
                    console.log("[OutpaintPanelV2] 绘制图片失败:", e);
                    // 如果绘制图片失败，回退到原来的红色矩形
                    this.drawFallbackImageArea(ctx, imgX, imgY, imgScaledW, imgScaledH);
                }
            } else {
                // 没有图片时绘制默认的红色区域
                this.drawFallbackImageArea(ctx, imgX, imgY, imgScaledW, imgScaledH);
            }
            
            // 移除调试信息
            // this.drawDebugInfo(ctx, previewArea, offsetX, offsetY, scaledW, scaledH, imgX, imgY, imgScaledW, imgScaledH);
            
            // 移除拖拽手柄（加号图标）
            // const handleX = imgX + imgScaledW / 2;
            // const handleY = imgY + imgScaledH / 2;
            
            // 根据是否有实际图片调整手柄样式
            // if (actualImage) {
            //     // 有图片时使用更突出的手柄样式
            //     ctx.fillStyle = "#ff6b35";
            //     ctx.beginPath();
            //     ctx.arc(handleX, handleY, 10, 0, 2 * Math.PI);
            //     ctx.fill();
            //     
            //     ctx.strokeStyle = "#ffffff";
            //     ctx.lineWidth = 3;
            //     ctx.beginPath();
            //     ctx.arc(handleX, handleY, 8, 0, 2 * Math.PI);
            //     ctx.stroke();
            //     
            //     // 绘制手柄中心的十字标记
            //     ctx.strokeStyle = "#ffffff";
            //     ctx.lineWidth = 2;
            //     ctx.beginPath();
            //     ctx.moveTo(handleX - 4, handleY);
            //     ctx.lineTo(handleX + 4, handleY);
            //     ctx.moveTo(handleX, handleY - 4);
            //     ctx.lineTo(handleX, handleY + 4);
            //     ctx.stroke();
            // } else {
            //     // 没有图片时使用原来的手柄样式
            //     ctx.fillStyle = "#ff6b35";
            //     ctx.beginPath();
            //     ctx.arc(handleX, handleY, 8, 0, 2 * Math.PI);
            //     ctx.fill();
            //     
            //     ctx.strokeStyle = "#ffffff";
            //     ctx.lineWidth = 2;
            //     ctx.beginPath();
            //     ctx.arc(handleX, handleY, 6, 0, 2 * Math.PI);
            //     ctx.stroke();
            // }
            
            // 绘制信息文本 - 修复超出节点边缘的问题
            if (this.properties.showInfo) {
                ctx.fillStyle = LiteGraph.NODE_TEXT_COLOR;
                ctx.font = "11px Arial";
                ctx.textAlign = "left";
                
                // 计算信息文本位置，确保不超出节点边界
                const infoY = Math.min(previewArea.y + previewArea.height + 15, this.size[1] - 60);
                const infoX = previewArea.x;
                const maxWidth = this.size[0] - 20; // 留出边距
                
                // 第一行：原图信息
                ctx.fillText(`原图: ${imgW}×${imgH}`, infoX, infoY);
                
                // 第二行：目标信息
                ctx.fillText(`目标: ${targetW}×${targetH}`, infoX, infoY + 15);
                
                // 第三行：位置信息
                ctx.fillText(`位置: (${this.properties.left}, ${this.properties.up})`, infoX, infoY + 30);
                
                // 显示图片加载状态
                const imageStatus = actualImage ? "✅ 图片已加载" : "⚠️ 等待图片输入";
                ctx.fillStyle = actualImage ? "#4CAF50" : "#FF9800";
                ctx.fillText(imageStatus, infoX, infoY + 45);
                
                // 显示拖拽模式 - 调整位置避免超出边界
                ctx.fillStyle = "#4CAF50";
                const modeText = "模式: 拖拽模式";
                const modeTextWidth = ctx.measureText(modeText).width;
                const modeX = Math.min(infoX + 200, this.size[0] - modeTextWidth - 10);
                ctx.fillText(modeText, modeX, infoY);
            }
            
            // 存储布局信息用于鼠标交互
            this.previewLayout = {
                offsetX, offsetY, scaledW, scaledH, scale,
                imgX, imgY, imgScaledW, imgScaledH,
                handleX: imgX + imgScaledW / 2, // 保留手柄位置用于其他功能
                handleY: imgY + imgScaledH / 2,
                previewArea: previewArea,
                canvasArea: { x: offsetX, y: offsetY, width: scaledW, height: scaledH }
            };
        }
        
        // 双击编辑数值
        this.node.onDblClick = function(e, pos, canvas)
        {
            if (!this.previewLayout) return false;
            
            const layout = this.previewLayout;
            const localX = e.canvasX - this.pos[0];
            const localY = e.canvasY - this.pos[1];
            
            // 检查是否点击在信息区域
            if (localY > layout.previewArea.y + layout.previewArea.height + 10) {
                if (localY < layout.previewArea.y + layout.previewArea.height + 25) {
                    // 编辑目标宽度
                    canvas.prompt("目标宽度", this.properties.targetWidth, 
                        function(v) {
                            const val = parseInt(v);
                            if (!isNaN(val) && val >= 64) {
                                this.properties.targetWidth = val;
                                let widthWidget = this.widgets.find(w => w.name === "width");
                                if (widthWidget) widthWidget.value = val;
                                this.updateProperties();
                                this.setDirtyCanvas(true);
                            }
                        }.bind(this), e);
                    return true;
                } else if (localY < layout.previewArea.y + layout.previewArea.height + 40) {
                    // 编辑目标高度
                    canvas.prompt("目标高度", this.properties.targetHeight,
                        function(v) {
                            const val = parseInt(v);
                            if (!isNaN(val) && val >= 64) {
                                this.properties.targetHeight = val;
                                let heightWidget = this.widgets.find(w => w.name === "height");
                                if (heightWidget) heightWidget.value = val;
                                this.updateProperties();
                                this.setDirtyCanvas(true);
                            }
                        }.bind(this), e);
                    return true;
                }
            }
            
            return false;
        }
        
        // 鼠标按下处理
        this.node.onMouseDown = function(e)
        {
            if (!this.previewLayout) return false;
            
            const layout = this.previewLayout;
            const localX = e.canvasX - this.pos[0];
            const localY = e.canvasY - this.pos[1];
            
            // 检查是否点击在拖拽手柄附近
            if (layout.handleX && layout.handleY) {
                const handleRadius = 15;
                const distanceToHandle = Math.sqrt(Math.pow(localX - layout.handleX, 2) + Math.pow(localY - layout.handleY, 2));
                
                if (distanceToHandle <= handleRadius) {
                    console.log("[OutpaintPanelV2] 开始拖拽，点击位置:", {localX, localY}, "手柄位置:", {handleX: layout.handleX, handleY: layout.handleY});
                    this.dragging = true;
                    this.captureInput(true);
                    this.updatePosition(e);
                    return true;
                }
            }
            
            // 也检查是否点击在原图区域内（用于拖拽整个原图）
            if (localX >= layout.imgX && localX <= layout.imgX + layout.imgScaledW &&
                localY >= layout.imgY && localY <= layout.imgY + layout.imgScaledH) {
                console.log("[OutpaintPanelV2] 点击在原图区域，开始拖拽");
                this.dragging = true;
                this.captureInput(true);
                this.updatePosition(e);
                return true;
            }
            
            return false;
        }
        
        // 鼠标移动处理
        this.node.onMouseMove = function(e, pos, canvas)
        {
            if (this.dragging) {
                if (canvas.pointer.isDown === false) {
                    this.onMouseUp(e);
                    return;
                }
                this.updatePosition(e);
            }
        }
        
        // 鼠标抬起处理
        this.node.onMouseUp = function()
        {
            if (this.dragging) {
                this.dragging = false;
                this.captureInput(false);
            }
        }
        
        // 失去选择时停止拖拽
        this.node.onSelected = function(e) {
            this.onMouseUp(e);
        }
        
        // 节点大小改变时的处理
        this.node.onResize = function(size) {
            console.log("[OutpaintPanelV2] 节点大小改变:", size);
            this.updateLayoutParameters();
            return size;
        }
        
        // 设置最小尺寸和计算合适的尺寸
        this.node.computeSize = function() {
            const minWidth = 360; // 增加最小宽度
            const minHeight = 600; // 适中的最小高度，足够显示拖拽界面
            
            // 计算widgets所需高度
            let widgetsHeight = 0;
            if (this.widgets) {
                for (let widget of this.widgets) {
                    if (!widget.hidden) {
                        widgetsHeight += LiteGraph.NODE_WIDGET_HEIGHT + 4;
                    }
                }
            }
            
            // 各部分高度
            const nodeHeaderHeight = 30;   // 节点标题栏
            const extraPadding = 25;       // widgets和预览区域间距
            const previewMinHeight = 250;  // 预览区域最小高度
            const bottomInfoHeight = 100;  // 底部信息区域
            const bottomPadding = 30;      // 底部边距
            
            // 计算总高度
            const calculatedHeight = Math.max(
                minHeight,
                nodeHeaderHeight + widgetsHeight + extraPadding + previewMinHeight + bottomInfoHeight + bottomPadding
            );
            
            console.log("[OutpaintPanelV2] 计算节点尺寸:", {
                minHeight: minHeight,
                widgetsHeight: widgetsHeight,
                calculatedHeight: calculatedHeight
            });
            
            return [minWidth, calculatedHeight];
        }
        
        // 更新位置（拖拽模式用）
        this.node.updatePosition = function(e)
        {
            if (!this.previewLayout) return;
            
            const layout = this.previewLayout;
            const localX = e.canvasX - this.pos[0];
            const localY = e.canvasY - this.pos[1];
            
            // 转换为目标坐标系
            const targetX = (localX - layout.offsetX) / layout.scale;
            const targetY = (localY - layout.offsetY) / layout.scale;
            
            // 计算原图左上角位置（以鼠标为中心）
            let newLeft = targetX - this.properties.imageWidth / 2;
            let newUp = targetY - this.properties.imageHeight / 2;
            
            // 边界约束
            const maxLeft = Math.max(0, this.properties.targetWidth - this.properties.imageWidth);
            const maxUp = Math.max(0, this.properties.targetHeight - this.properties.imageHeight);
            
            newLeft = Math.max(0, Math.min(newLeft, maxLeft));
            newUp = Math.max(0, Math.min(newUp, maxUp));
            
            // 网格吸附（按住Shift键时）
            if (e.shiftKey) {
                const gridSize = 8;
                newLeft = Math.round(newLeft / gridSize) * gridSize;
                newUp = Math.round(newUp / gridSize) * gridSize;
            }
            
            // 更新属性
            this.properties.left = Math.round(newLeft);
            this.properties.up = Math.round(newUp);
            
            // 严格只更新位置相关的widgets，防止影响其他参数
            if (this.widgets && this.widgets.length >= 4) {
                // 设置更新标志，防止循环触发
                this.updating = true;
                
                try {
                    // 通过名称查找widgets，更准确
                    let upWidget = this.widgets.find(w => w.name === "up");
                    let leftWidget = this.widgets.find(w => w.name === "left");
                    
                    if (upWidget) {
                        upWidget.value = this.properties.up;
                    }
                    if (leftWidget) {
                        leftWidget.value = this.properties.left;
                    }
                    
                    console.log("[OutpaintPanelV2] 拖拽更新位置:", {
                        up: this.properties.up,
                        left: this.properties.left
                    });
                } catch (e) {
                    console.error("[OutpaintPanelV2] 拖拽更新错误:", e);
                } finally {
                    this.updating = false;
                }
            }
            
            // 标记图需要更新
            if (this.graph) {
                this.graph.setisChangedFlag(this.id);
            }
        }
    }
}

// 注册扩展
app.registerExtension(
{
    name: "OutpaintPanelV2",
    async beforeRegisterNodeDef(nodeType, nodeData, _app)
    {
        if (nodeData.name === "XHH_OutpaintPanelV2")
        {
            const onNodeCreated = nodeType.prototype.onNodeCreated;
            nodeType.prototype.onNodeCreated = function () {
                if (onNodeCreated) onNodeCreated.apply(this, []);
                this.outpaintPanel = new OutpaintPanelV2(this);
            }
        }
    }
}); 